#include "StdAfx.h"
#include "../vfs/FileDescriptor.h"
#include "../vfs/DirectoryLibrary.h"

namespace ja2{ namespace vfs
{

	//! Iterator implementation.
	class DirectoryLibrary::IteratorImpl : public IDirectory::Iterator::IImplementation
	{
		// Attributes
	private:
		//! Parent class.
		DirectoryLibrary &m_Parent;
		//! Actual location.
		FileCatalog_t::const_iterator m_Iter;

		// Operations
	private:
		//! Get value.
		virtual FileProxy value() const;
		//! Move to next.
		virtual void increment();
		//! Compare with other.
		virtual bool equal(IImplementation const &Right) const;
		//! Clone the instance.
		virtual std::unique_ptr<IImplementation> clone() const;

		// Construction
	public:
		IteratorImpl(DirectoryLibrary &Parent, FileCatalog_t::const_iterator const &Iterator);
	};

	DirectoryLibrary::IteratorImpl::IteratorImpl(DirectoryLibrary &Parent, FileCatalog_t::const_iterator const &Iterator)
		: m_Parent(Parent), m_Iter(Iterator)
	{
	}

	FileProxy DirectoryLibrary::IteratorImpl::value() const
	{
		return m_Parent.get_file(m_Iter->first);
	}
		
	void DirectoryLibrary::IteratorImpl::increment()
	{
		++m_Iter;
	}
		
	bool DirectoryLibrary::IteratorImpl::equal(IImplementation const &Right) const
	{
		return (m_Iter == static_cast<IteratorImpl const &>(Right).m_Iter);
	}
		
	std::unique_ptr<IDirectory::Iterator::IImplementation> DirectoryLibrary::IteratorImpl::clone() const
	{
		return std::unique_ptr<IDirectory::Iterator::IImplementation>(new IteratorImpl(m_Parent, m_Iter));
	}

	//--------------------------//

	DirectoryLibrary::DirectoryLibrary(boost::filesystem::path const &MountPoint, boost::filesystem::path const &RealPath)
		: DirectoryBase(MountPoint, RealPath)
	{
	}

	bool DirectoryLibrary::file_exist(boost::filesystem::path const &File) const
	{
		return (m_FileCatalog.count(File) == 1);
	}

	void DirectoryLibrary::add_file(FileDescriptorPtr_t const &pFileDesc, bool DeleteOldFile)
	{
		boost::filesystem::path const &file_name = pFileDesc->get_file_name();
		// File exist and shouldn't be overwritten, do nothing
		if(file_exist(file_name) && !DeleteOldFile)
			return;
		// Add/replace
		m_FileCatalog[file_name] = pFileDesc;
	}

	void DirectoryLibrary::create_subdirectory(boost::filesystem::path const &/*SubDir*/)
	{
		throw RuntimeException(resources::NOT_IMPLEMENTED);
	}

	void DirectoryLibrary::delete_subdirectory(boost::filesystem::path const &/*Dir*/)
	{
		throw RuntimeException(resources::NOT_IMPLEMENTED);
	}

	void DirectoryLibrary::delete_file(boost::filesystem::path const &/*File*/)
	{
		throw RuntimeException(resources::NOT_IMPLEMENTED);
	}

	FileProxy DirectoryLibrary::get_file(boost::filesystem::path const &File_) const
	{
		// Create file
		return FileProxy(m_FileCatalog.find(File_)->second);
	}

	PathVector_t DirectoryLibrary::get_sub_dirs() const
	{
		// No sub-dirs here
		return PathVector_t();
	}

	DirectoryLibrary::Iterator DirectoryLibrary::begin()
	{
		return Iterator(new IteratorImpl(*this, m_FileCatalog.begin()));
	}

	DirectoryLibrary::Iterator DirectoryLibrary::end()
	{
		return Iterator(new IteratorImpl(*this, m_FileCatalog.end()));
	}
} /*vfs*/} /*ja2*/